﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Workbench.Models;
using Workbench.Persistance;

namespace Workbench.Operations
{
    public static class ExerciseOperations
    {
        public static ExerciseSuiteModel CreateTestSuite(string name)
        {
            var repository = DBContext.Current.GetExercisesRepository();
            var model = new ExerciseSuiteModel(name);
            repository.PersistExerciseSuite(model);
            return model;
        }
        
        public static ConcordancerExerciseModel CreateConcordancerExercise(List<WordWithNearWordsModel> nearWordModels, WordSuggestionModel word)
        {
            return CreateConcordancerExercise("Unnamed", nearWordModels, word);
        }

        public static ConcordancerExerciseModel CreateConcordancerExercise(string name, List<WordWithNearWordsModel> nearWordModels, WordSuggestionModel word)
        {
            var repository = DBContext.Current.GetExercisesRepository();
            var sentenceIds = nearWordModels.Select(x=>x.SentenceId).ToList();
            var model = new ConcordancerExerciseModel(name, sentenceIds, word);
            repository.PersistConcordancerExercise(model);
            return model;
        }

        public static void AddToSuite(ExerciseSuiteModel suiteModel, ConcordancerExerciseModel exerciseModel)
        {
            var repository = DBContext.Current.GetExercisesRepository();
            repository.RelateSuiteAndExercise(suiteModel.RowId, exerciseModel.RowId);
            suiteModel.Exercises.Add(exerciseModel);
        }

        public static ExerciseSuiteModel GetTestSuite(string name)
        {
            var repository = DBContext.Current.GetExercisesRepository();
            var model = repository.GetTestSuite(name);
            return model;
        }

        public static List<ConcordancerExerciseModel> GetExercises(ExerciseSuiteModel suite)
        {
            var repository = DBContext.Current.GetExercisesRepository();
            var result = repository.GetExercises(suite.RowId);
            return result;
        }

        public static string EmptyWordString = "............";

        public static string ExportAsText(ConcordancerExerciseModel concordancerExerciseModel)
        {
            var textRepository = DBContext.Current.GetTextRepository();
            var lemmatizerRepository = DBContext.Current.GetLemmatizerRepository();

            var sb = new StringBuilder();
            sb.AppendLine(concordancerExerciseModel.Name);
            sb.AppendLine();

            Func<WordModel, SuggestionType, long, bool> cmp = (w, type, id) =>
            {
                if (type == SuggestionType.WordForm)
                {
                    return w.UniqueWord.RowId == concordancerExerciseModel.Word.RowId;
                }
                else // == BaseForm
                {
                    return w.BaseForm != null ? w.BaseForm.RowId == concordancerExerciseModel.Word.RowId : false;
                }
            };

            foreach(var sentenceId in concordancerExerciseModel.SentenceIds)
            {
                var sentenceContent = textRepository.GetSentenceContent(sentenceId);
                var wordsInSentence = lemmatizerRepository.GetAllWords(sentenceId);

                foreach(var word in wordsInSentence)
                {

                    if(cmp(word, concordancerExerciseModel.Word.SuggestionType, concordancerExerciseModel.Word.RowId))
                    {
                        var startPositions = prepareStartPositions(sentenceContent, wordsInSentence);
                        sentenceContent = string.Format("{0}{1}{2}",
                            sentenceContent.Substring(0, startPositions[word.RowId]),
                            EmptyWordString,
                            sentenceContent.Substring(startPositions[word.RowId] + word.UniqueWord.Content.Length)
                        );
                    }
                }
                sb.AppendLine(sentenceContent);
            }
            return sb.ToString();
        }

        private static Dictionary<long, int> prepareStartPositions(string sentence, List<WordModel> words)
        {
            int startposition = 0;
            var result = new Dictionary<long, int>();
            for(int i = 0; i < words.Count; i++)
            {
                var word = words[i];
                var sp = sentence.IndexOf(word.GetContent(), startposition);
                result.Add(word.RowId, sp);
                startposition = sp + word.GetContent().Length;
                Debug.Assert(sentence.Length > startposition);
            }
            return result;
        }

        public static List<ExerciseSuiteModel> GetTestSuites()
        {
            var repo = DBContext.Current.GetExercisesRepository();
            return repo.GetAllExerciseSuites();
        }

        public static void DeleteConcordancerExercise(ConcordancerExerciseModel exerciseModel)
        {
            var repo = DBContext.Current.GetExercisesRepository();
            repo.DeleteExercise(exerciseModel);
        }

        public static void DeleteExerciseSuite(ExerciseSuiteModel exerciseSuiteModel)
        {
            var repo = DBContext.Current.GetExercisesRepository();
            repo.DeleteExerciseSuite(exerciseSuiteModel);
        }
    }
}
